SurfaceFlinger 中的 Layer 树构建过程分析

8/28/2024

# 1. 引子

SurfaceFlinger 中也有一颗树,与 WMS 中的窗口容器树相对应,树的节点类型是 Layer,所以我们称之为 Layer 树。不同于 WMS, SurfaceFlinger 中没有复杂的构建 Layer 树的逻辑,那 SurfaceFilinger 中如何构建出这颗树呢?WMS 这边创建一个窗口容器树节点的同时,会创建一个 SurfaceControl 对象,这个过程中会向 SurfaceFlinger 发起远程调用,SurfaceFlinger 端会创建一个对应的 Layer 对象。

# 2. Layer 树的创建过程

两个关键点:

  • Layer 创建的时机,根节点和非根节点是不同的
  • Layer 之间父子关系的建立

# 2.1 Layer 树根节点的创建过程

前文我们说到,在系统启动时,会去构建窗口容器树,在这个过程中会调用到 DisplayContent 的构造函数:

// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
    
    DisplayContent(Display display, RootWindowContainer root,
            @NonNull DeviceStateController deviceStateController) {
         // .....
        configureSurfaces(pendingTransaction);     
        // .....           
    }
1
2
3
4
5
6
7
8

DisplayContent 的构造函数中会调用到 configureSurfaces 方法:

// # DisplayContent
    private final SurfaceSession mSession = new SurfaceSession();

    private void configureSurfaces(Transaction transaction) {
        // 构建一个SurfaceControl
        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
                .setOpaque(true)
                .setContainerLayer() // 设置为容器类型的Layer
                .setCallsite("DisplayContent");
        // 设置名字后构建 (Display 0 name="XXX")
        mSurfaceControl = b.setName(getName()).setContainerLayer().build();
        //......
    }
1
2
3
4
5
6
7
8
9
10
11
12
13

这里会构建一个 SurfaceControl 对象,在构建 SurfaceControl 对象的过程中会向 SurfaceFlinger 发起远程调用,SurfaceFlinger 会创建一个与 DisplayContent 对应的 Layer 对象。

SurfaceControl 创建的细节不是本文的重点,这部分会在现实系统部分讲解。

此时,根节点 DisplayContent 对应的 Layer 已经构建好了。

# 2.2 Layer 树其他节点的创建过程

Layer 树其他节点的创建过程就要复杂一点了。

在 PendingArea 树转换过程中,会调用到 PendingArea root 节点的 instantiateChildren 方法.

   // #PendingArea 

        void instantiateChildren(DisplayArea<DisplayArea> parent, DisplayArea.Tokens[] areaForLayer,
                int level, Map<Feature, List<DisplayArea<WindowContainer>>> areas) {
            mChildren.sort(Comparator.comparingInt(pendingArea -> pendingArea.mMinLayer));
            // 遍历每一个子节点
            for (int i = 0; i < mChildren.size(); i++) {
                final PendingArea child = mChildren.get(i);
                // PendingArea -> DisplayArea
                final DisplayArea area = child.createArea(parent, areaForLayer);
                if (area == null) {
                    // TaskDisplayArea and ImeContainer can be set at different hierarchy, so it can
                    // be null.
                    continue;
                }
                // 这里的 parent 就是 DisplayContent
                parent.addChild(area, WindowContainer.POSITION_TOP);
                if (child.mFeature != null) {
                    areas.get(child.mFeature).add(area);
                }

                // 递归调用
                child.instantiateChildren(area, areaForLayer, level + 1, areas); 
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这里会把 PendingArea 转换为 DisplayArea,然后通过 addChild 建立起 DisplayArea 之间的树关系,

其中很重要的一点,addChild 中还会构建当前节点的 SurfaceControl,与之同时会远程访问到 SurfaceFlinger,SurfaceFlinger 中创建对应的 Layer 对象。

addChild 定义在父类 WindowContainer 中:

// # WindowContainer

   protected final WindowList<E> mChildren = new WindowList<E>();

    void addChild(E child, int index) {
        if (!child.mReparenting && child.getParent() != null) {
            throw new IllegalArgumentException("addChild: container=" + child.getName()
                    + " is already a child of container=" + child.getParent().getName()
                    + " can't add to container=" + getName()
                    + "\n callers=" + Debug.getCallers(15, "\n"));
        }

        if ((index < 0 && index != POSITION_BOTTOM)
                || (index > mChildren.size() && index != POSITION_TOP)) {
            throw new IllegalArgumentException("addChild: invalid position=" + index
                    + ", children number=" + mChildren.size());
        }

        if (index == POSITION_TOP) {
            index = mChildren.size();
        } else if (index == POSITION_BOTTOM) {
            index = 0;
        }

       // 建立树关系
        mChildren.add(index, child);

        // 关注点
        child.setParent(this);
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

setParent 方法具体代码如下:

// # WindowContainer

    // 父节点,这里就是 DisplayContent
    private WindowContainer<WindowContainer> mParent = null;

    final protected void setParent(WindowContainer<WindowContainer> parent) {
         // ......
            // 关注点
            onParentChanged(mParent, oldParent);
         // ......
    }
1
2
3
4
5
6
7
8
9
10
11

onParentChanged 的实现如下:

// # WindowContainer

   void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
         PreAssignChildLayersCallback callback) {
      super.onParentChanged(newParent, oldParent);
      // mParent 是 DisplayContent
      if (mParent == null) {
         return;
      }

      if (mSurfaceControl == null) { // 当前节点的 mSurfaceControl 为 null
         // If we don't yet have a surface, but we now have a parent, we should
         // build a surface.
         // 关注点
         createSurfaceControl(false /*force*/);
      } else {
         //......
         reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);
      }
      //......
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这里会调用 createSurfaceControl 去创建 Surface:

// # WindowContainer
   // 触发Surface的创建
   void createSurfaceControl(boolean force) {
        setInitialSurfaceControlProperties(makeSurface());
   }
1
2
3
4
5

当前代码是在 DisplayContent 的子节点 child 中。

makeSurface 的实现如下:

// # WindowContainer

   // 当前容器的 Surface
   protected SurfaceControl mSurfaceControl;

   SurfaceControl.Builder makeSurface() {
      // 拿到父节点 DisplayContent,调用 makeChildSurface
      final WindowContainer p = getParent();
      return p.makeChildSurface(this);
   }
1
2
3
4
5
6
7
8
9
10

DisplayContent 中覆写了 makeChildSurface 方法:

 // # DisplayContent
    SurfaceControl.Builder makeChildSurface(WindowContainer child) {

        SurfaceSession s = child != null ? child.getSession() : getSession();
        final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
        if (child == null) {
            return b;
        }

        return b.setName(child.getName())
                .setParent(mSurfaceControl);
    }
1
2
3
4
5
6
7
8
9
10
11
12

这里会创建好 child 的 SurfaceControl, SurfaceFlinger 侧会初始化好对应的 Layer。

setParent 方法调用,会配置好 Layer 的父节点。

如果非 DisplayContent 节点,就会执行到 WindowContainer 中的实现:

// # WindowContainer 中的实现
   SurfaceControl.Builder makeChildSurface(WindowContainer child) {
      // 拿到父亲
      final WindowContainer p = getParent();
      // Give the parent a chance to set properties. In hierarchy v1 we rely
      // on this to set full-screen dimensions on all our Surface-less Layers.
      // 调用父亲的 makeChildSurface 方法,再调用 setParent 
      return p.makeChildSurface(child)
                .setParent(mSurfaceControl);
   }
1
2
3
4
5
6
7
8
9
10

这里的 makeChildSurface 会一直递归调用,直到 getParent() 返回的是 DisplayContent 为止。然后调用到上面的 DisplayContent 中的 makeChildSurface 方法,构建好 SurfaceControl 和 Layer

Layer 之间的关系,通过这里的 setParent 方法调用建立。